package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.exceptions.LyException;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.*;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.leyou.common.constants.MQConstants.*;

@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {
    @Resource
    private BrandService brandService;
    @Resource
    private CategoryService categoryService;
    @Resource
    private SpuDetailService spuDetailService;
    @Resource
    private SkuService skuService;
    @Resource
    private SpuService spuService;
    @Resource
    private AmqpTemplate amqpTemplate;

    //分页查询商品
    @Override
    public PageDTO<SpuDTO> querySpuByPage(Integer page, Integer rows, Boolean saleable, Long categoryId, Long brandId, Long id) {
        //1.分页信息的健壮性处理
        page = Math.max(page, 1);//当前页码要大于1
        rows = Math.max(rows, 5);//每页大小至少为5
        Page<Spu> spuPage = query()
                .eq(saleable != null, "saleable", saleable)
                .eq(categoryId != null, "cid3", categoryId)
                .eq(brandId != null, "brand_id", brandId)
                .eq(id != null, "id", id)
                .page(new Page<>(page, rows));
        //2.获取分页信息详情
        long pages = spuPage.getPages();
        long total = spuPage.getTotal();
        List<Spu> spuList = spuPage.getRecords();
        //3.转换为DTO
        List<SpuDTO> dtoList = SpuDTO.convertEntityList(spuList);
        for (SpuDTO spuDTO : dtoList) {
            //在SpuDTO中添加商品品牌和分类
            addCategoryAndBrandName(spuDTO);
        }
        return new PageDTO<>(total, pages, dtoList);
    }

    //新增商品
    @Transactional
    @Override
    public void saveGoods(SpuDTO spuDTO) {
        //1.新增spu,并设置为未上架
        Spu spu = spuDTO.toEntity(Spu.class);
        spu.setSaleable(false);
        boolean success = save(spu);
        if (!success) {
            throw new LyException(500, "新增商品失败");
        }
        //2.新增SpuDetail
        SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
        spuDetail.setSpuId(spu.getId());
        success = spuDetailService.save(spuDetail);
        if (!success) {
            throw new LyException(500, "新增商品详情失败");
        }
        //3.新增skus
        List<SkuDTO> skuDTOS = spuDTO.getSkus();
        //SkuDTO转换成sku,并设置未传入的参数
        List<Sku> skuList = skuDTOS.stream().map(skuDTO -> {
            Sku sku = skuDTO.toEntity(Sku.class);
            sku.setSaleable(false);
            sku.setSpuId(spu.getId());
            return sku;
        }).collect(Collectors.toList());
        skuService.saveBatch(skuList);
    }

    /**
     * 修改商品上下架，并发送消息到mq
     *
     * @param id       商品spu的id
     * @param saleable true：上架；false：下架
     */
    @Transactional
    @Override
    public void updateSpuSaleable(Long id, Boolean saleable) {
        //1.更新Spu
        Spu spu = spuService.getById(id);
        spu.setSaleable(saleable);
        boolean success = updateById(spu);
        if (!success) {
            throw new LyException(500, "更新Spu上下架失败");
        }
        //2.更新Sku
        success = skuService.update().eq("spu_id", id).set("saleable", saleable).update();
        if (!success) {
            throw new LyException(500, "更新Sku上下架失败");
        }
        //3.发送MQ消息
        String routingKey = saleable ? RoutingKeyConstants.ITEM_UP_KEY : RoutingKeyConstants.ITEM_DOWN_KEY;
        amqpTemplate.convertAndSend(ExchangeConstants.ITEM_EXCHANGE_NAME, routingKey, id);
    }

    /**
     * 根据id查询商品
     *
     * @param id 商品id
     * @return 商品信息
     */
    @Override
    public SpuDTO queryGoodsById(Long id) {
        //1.查询spu
        Spu spu = getById(id);
        if (spu == null) {
            throw new LyException(400, "商品id不存在！");
        }
        SpuDTO spuDTO = new SpuDTO(spu);
        //2.查询spuDetail
        SpuDetail spuDetail = spuDetailService.getById(id);
        if (spuDetail == null) {
            throw new LyException(400, "商品id不存在！");
        }
        spuDTO.setSpuDetail(new SpuDetailDTO(spuDetail));
        //3.查询sku集合
        List<Sku> skuList = skuService.query().eq("spu_id", id).list();
        if (CollectionUtils.isEmpty(skuList)) {
            throw new LyException(400, "商品id不存在！");
        }
        spuDTO.setSkus(SkuDTO.convertEntityList(skuList));
        //最后在SpuDTO中添加品牌和分类
        addCategoryAndBrandName(spuDTO);
        return spuDTO;
    }

    //修改商品（**）
    @Transactional
    @Override
    public void updateGoods(SpuDTO spuDTO) {
        //1.判断是否包含spu
        Long spuDTOId = spuDTO.getId();
        if (spuDTOId != null) {
            //存在spu的id，spu需要修改
            Spu spu = spuDTO.toEntity(Spu.class);
            boolean success = updateById(spu);
            if (!success) {
                throw new LyException(500, "更新商品失败！");
            }
        }
        //2.判断是否包含spuDetail
        SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
        if (spuDetailDTO != null && spuDetailDTO.getSpuId() != null) {
            //spuDetail存在，需要修改
            SpuDetail spuDetail = spuDetailDTO.toEntity(SpuDetail.class);
            boolean success = spuDetailService.updateById(spuDetail);
            if (!success) {
                throw new LyException(500, "更新商品失败！");
            }
        }
        //3.判断是否包含sku
        List<SkuDTO> skuDTOList = spuDTO.getSkus();
        //如果sku不存在，不修改
        if (CollectionUtils.isEmpty(skuDTOList)) {
            return;
        }
        //sku存在，将sku根据有没有saleable来分组。有是新增或修改的sku，没有是删除的sku
        Map<Boolean, List<Sku>> map = skuDTOList.stream().map(skuDTO -> skuDTO.toEntity(Sku.class))
                .collect(Collectors.groupingBy(sku -> sku.getSaleable() == null));
        List<Sku> updateSkuList = map.get(true);
        //存在要新增或修改的sku
        if (!CollectionUtils.isEmpty(updateSkuList)) {
            //批量更新sku
            skuService.saveOrUpdateBatch(updateSkuList);
        }
        List<Sku> deleteSkuList = map.get(false);
        //存在要删除的sku
        if (!CollectionUtils.isEmpty(deleteSkuList)) {
            //批量删除sku
            List<Long> ids = deleteSkuList.stream().map(Sku::getId).collect(Collectors.toList());
            skuService.removeByIds(ids);
        }

    }

    private void addCategoryAndBrandName(SpuDTO spuDTO) {
        //在SpuDTO中添加品牌
        Brand brand = brandService.getById(spuDTO.getBrandId());
        spuDTO.setBrandName(brand.getName());
        //在SpuDTO中添加分类
        List<Category> categoryList = categoryService.listByIds(spuDTO.getCategoryIds());
        String name = categoryList.stream().map(Category::getName).collect(Collectors.joining("/"));//拼接分类名称
        spuDTO.setCategoryName(name);
    }


}
